package com.code.translate.httpbuilder;

import com.code.translate.enums.Constants;
import com.code.translate.utils.IOUtils;
import com.code.translate.utils.RandomUtils;
import com.code.translate.utils.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.nio.charset.Charset;
import java.util.Map;

/**
 * @author ggh
 * @date 2022/8/9
 */
public class MultipartFormDataBuilder extends ContentTypeBuilder {
    private static final String PREFIX = "----WebKitFormBoundary";
    private static final String PREFIXSHORT = "--";
    private static final String LINE = "\r\n";
    private static final String CONTENT_TYPE = "application/json";
    private ThreadLocal<String> boundary = ThreadLocal.withInitial(() -> RandomUtils.nextString(16));

    @Override
    public void headerbuilder(HttpURLConnection connection, Map<String, String> headers) throws Exception {
        super.headerbuilder(connection, headers);
        connection.setRequestProperty(HttpHeaders.CONTENT_TYPE, "multipart/form-data; boundary=" + PREFIX + boundary.get());
        connection.setRequestProperty(HttpHeaders.ACCEPT, "application/json, text/plain, */*");
    }

    @Override
    public void bodybuilder(OutputStream os, Map<String, Object> params) throws IOException {
        StringBuilder builder = new StringBuilder();

        String fileContentType = (String) params.get(Constants.FILE_CONTENT_TYPE);
        if (StringUtils.isEmpty(fileContentType)) {
            fileContentType = CONTENT_TYPE;
        } else {
            params.remove(Constants.FILE_CONTENT_TYPE);
        }

        if (!CollectionUtils.isEmpty(params)) {
            // 参数上传
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                if (!(entry.getValue() instanceof File || entry.getValue() instanceof InputStream || entry.getValue() instanceof byte[])) {
                    builder.append(PREFIXSHORT + PREFIX + boundary.get());
                    builder.append(LINE);
                    builder.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINE);
                    builder.append(LINE);
                    builder.append(entry.getValue().toString());
                    builder.append(LINE);
                }
            }
            os.write(builder.toString().getBytes());
            os.flush();

            //文件上传
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                if (entry.getValue() instanceof File) {
                    builder = new StringBuilder();

                    builder.append(PREFIXSHORT + PREFIX + boundary.get());
                    builder.append(LINE);

                    File file = (File) entry.getValue();
                    builder.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"; filename=\"" + file.getName() + "\"" + LINE);
                    builder.append("Content-Type: " + fileContentType + LINE);
                    builder.append(LINE);

                    os.write(builder.toString().getBytes());
                    os.flush();

                    IOUtils.writeStream(new FileInputStream(file), os, Charset.defaultCharset());
                    os.write(LINE.getBytes());
                } else if (entry.getValue() instanceof InputStream) {
                    builder = new StringBuilder();

                    builder.append(PREFIXSHORT + PREFIX + boundary.get());
                    builder.append(LINE);

                    InputStream is = (InputStream) entry.getValue();
                    builder.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"; filename=\"" + RandomUtils.nextString(2) + ".jpg\"" + LINE);
                    builder.append("Content-Type: " + fileContentType + LINE);
                    builder.append(LINE);

                    os.write(builder.toString().getBytes());
                    os.flush();

                    IOUtils.writeStream(is, os, Charset.defaultCharset());
                    os.write(LINE.getBytes());
                } else if (entry.getValue() instanceof byte[]) {
                    builder = new StringBuilder();

                    builder.append(PREFIXSHORT + PREFIX + boundary.get());
                    builder.append(LINE);

                    byte[] bus = (byte[]) entry.getValue();
                    System.out.println(bus.length);
                    builder.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"; filename=\"" + RandomUtils.nextString(2) + ".jpg\"" + LINE);
                    builder.append("Content-Type: " + fileContentType + LINE);
                    builder.append(LINE);

                    os.write(builder.toString().getBytes());
                    os.flush();

                    IOUtils.writeInputStreamFromByteArray(os, bus);
                    os.write(LINE.getBytes());
                }

            }
        }
        String end = PREFIXSHORT + PREFIX + boundary.get() + PREFIXSHORT + LINE;
        os.write(end.getBytes());
        os.flush();
    }

    @Override
    public boolean isPresent(String content) {
        return content.contains(MediaType.MULTIPART_FORM_DATA_VALUE);
    }
}
